import Vue from "vue";

export let busVue = new Vue();

export const UU = "Syx-";

// 随机不重复字符串
export const CreateUniqueId = (n) => {
  var random = function () {
    return Number(Math.random().toString().substr(2)).toString(36);
  };
  var arr = [];

  function createId() {
    var num = random();
    var _bool = false;
    arr.forEach((v) => {
      if (v === num) _bool = true;
    });
    if (_bool) {
      createId();
    } else {
      arr.push(UU + num);
    }
  }
  var i = 0;
  while (i < n) {
    createId();
    i++;
  }
  return arr;
};

// 下载
export const downloadImage = (url, type = "png") => {
  fetch(url)
    .then(async (res) => await res.blob())
    .then((blob) => {
      const a = document.createElement("a");
      a.style.display = "none";
      a.href = URL.createObjectURL(blob);
      a.download = CreateUniqueId(1)[0] + "." + type;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(a.href);
    });
};

// 获取url参数
export const getUrlParam = (name) => {
  let reg = new RegExp("(^|&?)" + name + "=([^&]*)(&|$)", "i");
  let r = window.location.href.substr(1).match(reg);
  if (r != null) {
    return decodeURI(r[2]);
  }
  return undefined;
};

// 本地存储
export const nativeplacestore = {
  set: function (name, value, type = 1, day) {
    let storage = type == 1 ? window.localStorage : window.sessionStorage;
    let d = new Date();
    let time = 0;
    day = typeof day === "undefined" || !day ? 1 : day;
    time = d.setHours(d.getHours() + 24 * day);
    storage.setItem(
      name,
      JSON.stringify({
        data: value,
        time: time,
      })
    );
  },
  get: function (name, type = 1) {
    let storage = type == 1 ? window.localStorage : window.sessionStorage;
    let data = storage.getItem(name);
    if (!data) {
      return null;
    }
    let obj = JSON.parse(data);
    if (new Date().getTime() > obj.time) {
      storage.removeItem(name);
      return null;
    } else {
      return obj.data;
    }
  },
  clear: function (name, type = 1) {
    let storage = type == 1 ? window.localStorage : window.sessionStorage;
    if (name) {
      storage.removeItem(name);
    } else {
      storage.clear();
    }
  },
};
/**
 * 获取某个月的总天数
 *
 */
export function getCountDays(year, month) {
  var date = new Date(year, month, 0);
  var days = date.getDate();
  return days;
}
// 时间格式化 【'yyyy-MM-dd hh:mm:ss',时间】
export const formatDate = function (fmt, date, type = 1) {
  if (typeof date !== "object") {
    date = !date ? new Date() : new Date(date);
  }
  if (type == 99) {
    return {
      yyyy: date.getFullYear(),
      MM:
        date.getMonth() + 1 < 10
          ? "0" + (date.getMonth() + 1)
          : date.getMonth() + 1,
      dd: date.getDate() < 10 ? "0" + date.getDate() : date.getDate(),
      hh: date.getHours() < 10 ? "0" + date.getHours() : date.getHours(),
      mm: date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(),
      ss: date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds(),
      days: new Date(
        date.getFullYear() + "-" + (date.getMonth() + 1) + "-1"
      ).getDay(),
      tshu: getCountDays(date.getFullYear(), date.getMonth() + 1),
      ms: stamp.getTime(date, 2),
    };
  }
  var o = {
    "M+": date.getMonth() + 1,
    "d+": date.getDate(),
    "h+": date.getHours(),
    "m+": date.getMinutes(),
    "s+": date.getSeconds(),
    "q+": Math.floor((date.getMonth() + 3) / 3),
    S: date.getMilliseconds(),
  };
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(
      RegExp.$1,
      (date.getFullYear() + "").substr(4 - RegExp.$1.length)
    );
  }
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(fmt)) {
      fmt = fmt.replace(
        RegExp.$1,
        RegExp.$1.length === 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
      );
    }
  }

  let weekday = [
    "星期日",
    "星期一",
    "星期二",
    "星期三",
    "星期四",
    "星期五",
    "星期六",
  ];

  return type == 1 ? fmt : fmt + " " + weekday[date.getDay()];
};

// josn方法
export const jsons = (json, types = 1) => {
  if (type(json) == "[object String]") {
    return types == 1 ? JSON.parse(json) : json;
  }
  return JSON.stringify(json);
};

// ajax操作
export const ajaxFh = ({
  url,
  method = "GET",
  data,
  ContentType = "application/json;charset=utf-8",
  Authorization,
  type = 2,
  z = 1,
}) => {
  let promise = new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          resolve(jsons(xhr.response, 2));
        } else {
          reject(new Error("error"));
        }
      }
    };
    if (method.toUpperCase() === "GET") {
      let paramsList = [];
      for (let key in data) {
        paramsList.push(key + "=" + data[key]);
      }
      let params = paramsList.join("&");
      url = url + "?" + params;
      xhr.open("get", url, false);
      xhr.send();
    } else if (method.toUpperCase() === "POST") {
      xhr.open("post", url, true);
      if (type == 2) xhr.setRequestHeader("Content-Type", ContentType);
      xhr.setRequestHeader("Authorization", Authorization);
      xhr.send(type == 1 ? data : jsons(data));
    }
  });
  return promise;
};

// fetch请求的封装
export const fetchFh = function ({ url, setting = {} }) {
  let opts = {
    method: (setting.method || "GET").toUpperCase(),
    headers: setting.headers || {},
  };
  let dataType = setting.dataType || "json";
  let data = setting.data || "";
  let paramsFormat = function (obj) {
    var str = "";
    for (var i in obj) {
      str += `${i}=${obj[i]}&`;
    }
    return str.split("").slice(0, -1).join("");
  };

  if (opts.method === "GET") {
    url = url + (data ? `?${paramsFormat(data)}` : "");
  } else {
    setting.body = data || {};
  }
  return new Promise((resolve, reject) => {
    fetch(url, opts)
      .then(async (res) => {
        let data =
          dataType === "text"
            ? await res.text()
            : dataType === "blob"
            ? await res.blob()
            : await res.json();
        resolve(data);
      })
      .catch((e) => {
        reject(e);
      });
  });
};

// 复制功能
export const copyTxt = function (text) {
  try {
    navigator.clipboard.writeText(text);
    console.log("页面内容已复制到剪贴板 ");
    return true;
  } catch (e) {
    console.log(`复制文案失败: ${e}`);
    return false;
  }
};

// 粘贴
export const getText = async () => {
  try {
    const text = await navigator.clipboard.readText();
    console.log(`粘贴内容: ${text}`);
    return text;
  } catch (e) {
    console.error(`从剪切板获取数据失败: ${e}`);
    return "";
  }
};

//判断两个数组是否相等
export const arrayEqual = function (arr1, arr2) {
  if (arr1 === arr2) return true;
  if (arr1.length != arr2.length) return false;
  if (jsons(arr1) === jsons(arr2)) return true;
  return false;
};

// 时间，10位时间戳转换
export const stamp = {
  getTime: function (time, type = 1) {
    let date = time ? new Date(time) : new Date();
    return type == 1 ? Math.round(date.getTime() / 1000) : date.getTime();
  },
  timeToStr: function (time, fmt = "yyyy-MM-dd", type = 1) {
    return type == 1
      ? formatDate(fmt, new Date(time * 1000))
      : formatDate(fmt, new Date(time));
  },
};

// 常用正则验证，注意type大小写
export const checkStr = function (str, type) {
  switch (type) {
    case "phone": // 手机号码
      return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(str);
    case "tel": // 座机
      return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
    case "card": // 身份证
      return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str);
    case "pwd": // 密码以字母开头，长度在6~18之间，只能包含字母、数字和下划线
      return /^[a-zA-Z]\w{5,17}$/.test(str);
    case "postal": // 邮政编码
      return /[1-9]\d{5}(?!\d)/.test(str);
    case "QQ": // QQ号
      return /^[1-9][0-9]{4,9}$/.test(str);
    case "email": // 邮箱
      return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
    case "money": // 金额(小数点2位)
      return /^\d*(?:\.\d{0,2})?$/.test(str);
    case "URL": // 网址
      return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(
        str
      );
    case "IP": // IP
      return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(
        str
      );
    case "date": // 日期时间
      return (
        /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(
          str
        ) || /^(\d{4})\-(\d{2})\-(\d{2})$/.test(str)
      );
    case "number": // 数字
      return /^[0-9]$/.test(str);
    case "english": // 英文
      return /^[a-zA-Z]+$/.test(str);
    case "chinese": // 中文
      return /^[\u4E00-\u9FA5]+$/.test(str);
    case "lower": // 小写
      return /^[a-z]+$/.test(str);
    case "upper": // 大写
      return /^[A-Z]+$/.test(str);
    case "HTML": // HTML标记
      return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str);
    default:
      return true;
  }
};

// 生成随机数范围
export const random = function (min = 1, max = 9) {
  if (arguments.length === 2) {
    return Math.floor(min + Math.random() * (max + 1 - min));
  } else {
    return null;
  }
};

// 将阿拉伯数字翻译成中文的大写数字
export const numberToChinese = function (num) {
  let AA = new Array(
    "零",
    "一",
    "二",
    "三",
    "四",
    "五",
    "六",
    "七",
    "八",
    "九",
    "十"
  );
  let BB = new Array("", "十", "百", "仟", "萬", "億", "点", "");
  let a = ("" + num).replace(/(^0*)/g, "").split(".");
  let k = 0;
  let re = "";
  for (let i = a[0].length - 1; i >= 0; i--) {
    switch (k) {
      case 0:
        re = BB[7] + re;
        break;
      case 4:
        if (!new RegExp("0{4}//d{" + (a[0].length - i - 1) + "}$").test(a[0])) {
          re = BB[4] + re;
        }
        break;
      case 8:
        re = BB[5] + re;
        BB[7] = BB[5];
        k = 0;
        break;
    }
    if (k % 4 === 2 && a[0].charAt(i + 2) !== 0 && a[0].charAt(i + 1) === 0) {
      re = AA[0] + re;
    }
    if (a[0].charAt(i) !== 0) {
      re = AA[a[0].charAt(i)] + BB[k % 4] + re;
    }
    k++;
  }
  if (a.length > 1) {
    re += BB[6];
    for (let i = 0; i < a[1].length; i++) {
      re += AA[a[1].charAt(i)];
    }
  }
  if (re === "一十") {
    re = "十";
  }
  if (re.match(/^一/) && re.length === 3) {
    re = re.replace("一", "");
  }
  return re;
};

//url参数转对象
export const parseQueryString = function (url) {
  url = !url ? window.location.href : url;
  if (url.indexOf("?") === -1) {
    return {};
  }
  let search =
    url[0] === "?" ? url.substr(1) : url.substring(url.lastIndexOf("?") + 1);
  if (search === "") {
    return {};
  }
  search = search.split("&");
  let query = {};
  for (let i = 0; i < search.length; i++) {
    let pair = search[i].split("=");
    query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || "");
  }
  return query;
};

//对象序列化【对象转url参数】
export const stringfyQueryString = function (obj) {
  if (!obj) return "";
  let pairs = [];
  for (let key in obj) {
    let value = obj[key];
    if (value instanceof Array) {
      for (let i = 0; i < value.length; ++i) {
        pairs.push(
          encodeURIComponent(key + "[" + i + "]") +
            "=" +
            encodeURIComponent(value[i])
        );
      }
      continue;
    }
    pairs.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
  }
  return pairs.join("&");
};

// 返回数据类型
export function type(para) {
  return Object.prototype.toString.call(para);
}

// 数组去重
export function unique(arr) {
  var obj = {};
  return arr.filter((ele) => {
    if (!obj[ele]) {
      obj[ele] = true;
      return true;
    }
  });
}

// 获取窗口尺寸
export function getViewportOffset() {
  if (window.innerWidth) {
    return {
      w: window.innerWidth,
      h: window.innerHeight,
    };
  } else {
    if (document.compatMode === "BackCompat") {
      return {
        w: document.body.clientWidth,
        h: document.body.clientHeight,
      };
    } else {
      return {
        w: document.documentElement.clientWidth,
        h: document.documentElement.clientHeight,
      };
    }
  }
}

// 深浅拷贝
export function deepClone(obj) {
  if (typeof obj !== "object" || obj === undefined) {
    return obj;
  }

  let result;
  if (obj instanceof Array) {
    result = [];
  } else {
    result = {};
  }

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      result[key] = deepClone(obj[key]);
    }
  }
  return result;
}

// 排序
export function sortOne(arr, z, type = 1) {
  let list = deepClone(arr);
  list.sort((a, b) => {
    if (type == 1) {
      return isStringSD(z) ? a - b : a[z] - b[z];
    }
    return isStringSD(z) ? b - a : b[z] - a[z];
  });
  return list;
}

// string 判断是否为 null undefined 空字符串
export function isStringSD(str = "") {
  if (str === "undefined" || str === undefined) {
    return true;
  }
  if (str === "null" || str === null) {
    return true;
  }
  if (str.trim() === "") {
    return true;
  }
  return false;
}

// 数组中是否包含某个值
export function arrIndexOf(arr, str, index = 1) {
  if (arr.indexOf(str) >= 0) {
    return index == 1 ? true : arr.indexOf(str);
  } else {
    return index == 1 ? false : -1;
  }
}

// 删除指定下标元素
export function arrSplice(arr, index, num = 1) {
  let list = deepClone(arr);
  list.splice(index, num);
  return list;
}

/**
 * 节流
 * @param {Function} func 要执行的回调函数
 * @param {Number} wait 延时的时间
 * @param {Boolean} immediate 是否立即执行
 * @return null
 */
let timer, flag;
export function throttle(func, wait = 300, immediate = true) {
  if (immediate) {
    if (!flag) {
      flag = true;
      // 如果是立即执行，则在wait毫秒内开始时执行
      typeof func === "function" && func();
      timer = setTimeout(() => {
        flag = false;
      }, wait);
    }
  } else {
    if (!flag) {
      flag = true;
      // 如果是非立即执行，则在wait毫秒内的结束处执行
      timer = setTimeout(() => {
        flag = false;
        typeof func === "function" && func();
      }, wait);
    }
  }
}
/**
 * 防抖
 * @param {Function} func 要执行的回调函数
 * @param {Number} wait 延时的时间
 * @param {Boolean} immediate 是否立即执行
 * @return null
 */
let timeout;
export function debounce(func, wait = 300, immediate = false) {
  // 清除定时器
  if (timeout !== null) clearTimeout(timeout);
  // 立即执行，此类情况一般用不到
  if (immediate) {
    var callNow = !timeout;
    timeout = setTimeout(function () {
      timeout = null;
    }, wait);
    if (callNow) typeof func === "function" && func();
  } else {
    // 设置定时器，当最后一次操作后，timeout不会再被清除，所以在延时wait毫秒后执行func回调方法
    timeout = setTimeout(function () {
      typeof func === "function" && func();
    }, wait);
  }
}

// 随机颜色
export function randomColor(i = 1) {
  var r = Math.floor(Math.random() * 256);
  var g = Math.floor(Math.random() * 256);
  var b = Math.floor(Math.random() * 256);
  return `rgba(${r},${g},${b},${i})`;
}

// 随机固定位数字母数字组成的字符串
export function randomWord(range = 4) {
  var str = "",
    arr = [
      "0",
      "1",
      "2",
      "3",
      "4",
      "5",
      "6",
      "7",
      "8",
      "9",
      "a",
      "b",
      "c",
      "d",
      "e",
      "f",
      "g",
      "h",
      "i",
      "j",
      "k",
      "l",
      "m",
      "n",
      "o",
      "p",
      "q",
      "r",
      "s",
      "t",
      "u",
      "v",
      "w",
      "x",
      "y",
      "z",
      "A",
      "B",
      "C",
      "D",
      "E",
      "F",
      "G",
      "H",
      "I",
      "J",
      "K",
      "L",
      "M",
      "N",
      "O",
      "P",
      "Q",
      "R",
      "S",
      "T",
      "U",
      "V",
      "W",
      "X",
      "Y",
      "Z",
    ];

  for (var i = 0; i < range; i++) {
    str += arr[random(0, arr.length - 1)];
  }
  return str;
}

// js获取数组最深层级
export function getArrayLayer(arr, attr, index = 1) {
  let newIndex = index;
  for (const iterator of arr) {
    let tempIndex = index;
    if (iterator[attr]) {
      tempIndex = getArrayLayer(iterator[attr], attr, index + 1);
      if (tempIndex > newIndex) {
        newIndex = tempIndex;
      }
    }
  }
  return newIndex;
}


export function flatten(tree) {
  return tree.reduce((res, item) => {
    const { children, ...i } = item;
    return res.concat(
      i,
      children && children.length ? treeToArray(children) : []
    );
  }, []);
}
function treeToArray(tree) {
  let res = []
  for (const item of tree) {
    const { children, ...i } = item
    if (children && children.length) {
      res = res.concat(treeToArray(children))
    }
    res.push(i)
  }
  return res
} 

export function arrayToTree(items) {
  let res = [] // 存放结果集
  let map = {}
  // 判断对象是否有某个属性
  let getHasOwnProperty = (obj, property) => Object.prototype.hasOwnProperty.call(obj, property)

  // 边做map存储，边找对应关系
  for (const i of items) {
      map[i.value] = {
          ...i,
          children: getHasOwnProperty(map, i.value) ? map[i.value].children : []
      }
      const newItem = map[i.value]
      if (i.pid === 0) {
          res.push(newItem)
      } else {
          if (!getHasOwnProperty(map, i.pid)) {
              map[i.pid] = {
                  children: []
              }
          }
          map[i.pid].children.push(newItem)
      }
  }
  return res
} 